﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows.Threading;
using SLS.Core.HLASimu;
using SLS.ExClassLib.Events;
using SLS.ExClassLib.Message;
namespace SLS.ExClassLib.Event
{ 
    public partial class EventDispatcher 
    {
 
        private ArrayList GetFederation(string CallerTye)
        {
            ArrayList federation = null;
            string m_FederationName = "";
            try
            {
                switch (CallerTye)
                {
                    case "UIFederate":
                    case "UIFederation":
                        m_FederationName = "UIFederation";
                        break;
                    case "WFFederate":
                    case "WFFederation":
                        m_FederationName = "WFFederation";
                        break;
                    case "HLAFederate":
                    case "HLAFederation":
                        m_FederationName = "HLAFederation";
                        break;
                    case "WFServiceFederate":
                    case "WFServiceFederation":
                        m_FederationName = "WFServiceFederation";
                        break;

                    default:
                        m_FederationName = "DefaultFederation";
                        break;
                }

                federation = FederationList[m_FederationName];
                if (federation == null)
                {
                    federation = new ArrayList();
                    FederationList.Add("UnknownFederation", federation);
                }
            }
            catch (Exception ex)
            {
                Tracer.Error(ex.StackTrace, ex);
            }
            return federation;
        }
        public object GetFederate(string CallerTye, MessageEx msg, object m_RTIServiceClient = null, string wfm = "")
        {
            object fed = null;
            string m_JobID = msg.JobID;
            if (wfm == "")
            {
                wfm = msg.Address;
            }
            ArrayList federation = GetFederation(CallerTye);
            try
            {
                var query = from Federate fedexist in federation
                            where fedexist.FEDName == wfm
                            select fedexist;

                foreach (Federate fedtemp in query)
                {
                    fed = fedtemp;
                }
                if (fed != null)
                {
                    return fed;
                }
                if (m_JobID == "OnJoinFederation")
                {
                    switch (CallerTye)
                    {
                        case "UIFederate":
                        case "UIFederation":
                        case "WFFederate":
                        case "WFFederation":
                        case "HLAFederate":
                        case "HLAFederation":
                        case "WFServiceFederate":
                        case "WFServiceFederation":
                            CallerTye = "UIFederation";
                            federation = GetFederation(CallerTye);
                            fed = new UIFederate(CallerTye, wfm, m_RTIServiceClient);
                            federation.Add(fed);
                            CallerTye = "WFFederation";
                            federation = GetFederation(CallerTye);
                            fed = new WFFederate(CallerTye, wfm, m_RTIServiceClient);
                            federation.Add(fed);
                            CallerTye = "HLAFederation";
                            federation = GetFederation(CallerTye);
                            fed = new HLAFederate(CallerTye, wfm, m_RTIServiceClient);
                            federation.Add(fed);
                            wfm = "WFServiceFederate";
                            CallerTye = "WFServiceFederation";
                            federation = GetFederation(CallerTye);
                            fed = new WFServiceFederate(CallerTye, wfm, m_RTIServiceClient);
                            federation.Add(fed);
                            break;
                        default:
                            break;
                    }
                    fed = null;
                    CallerTye = "HLAFederation";
                    federation = GetFederation(CallerTye);
                    query = from Federate fedexist in federation
                            where fedexist.FEDName == wfm
                            select fedexist;
                    int a = query.Count();
                    foreach (Federate fedtemp in query)
                    {
                        fed = fedtemp;
                    }
                    if (fed == null)
                    {
                        fed = new HLAFederate("HLAFederation", wfm, m_RTIServiceClient);
                        federation.Add(fed);
                    }
                }
                if (fed == null)
                {
                    Tracer.Warn(this.ToString(), "Federate must at first join the federation before receiving any message" + msg.Address);
                }
            }
            catch (Exception ex)
            {
                Tracer.Error(ex.StackTrace, ex);
            }
            return fed;
        }

        #region =================STATUS BAR=================
        /// <summary>
        /// Event delegate
        /// </summary>
        public event EventHandler<StatusEventArgs> OnStatusChange;

        /// <summary>
        /// Internal function to raise a status (bar) event
        /// </summary>
        /// <param name="type"></param>
        public void RaiseStatus(string message, StatusEventType type)
        {
            Trace.TraceInformation(message);

            if (CheckAccess())
            {
                StatusEventArgs args = new StatusEventArgs(type, message);

                if (OnStatusChange != null)
                    OnStatusChange(this, args);
                /*
                //raise event only if it contains message
                if (message != string.Empty)
                    RaiseMessage(args);
                */
            }
            else
                Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate
                {
                    StatusEventArgs args = new StatusEventArgs(type, message);

                    if (OnStatusChange != null)
                        OnStatusChange(this, args);
                    /*
                    //raise event only if it contains message
                    if (message != string.Empty)
                        RaiseMessage(args);
                    */
                });
        }

        #endregion
         
        #region =================WORKFLOWSERVICE=================
        /*
          public void RECVRTIMessage(MessageEx msg)
        {
            try
            {
                HLAFederate fed = null;
                fed = (HLAFederate)GetFederate("HLAFederate", msg);
                if (fed != null)
                {
                    msg.JobType = "RTI2FED";
                    fed.BuildWorkQueue(msg);
                }
            }
            catch (Exception ex)
            {
                Tracer.Error(ex.StackTrace, ex);
            }
        }
        public void POSTWF2UIMessage(MessageEx msg, object Data = null, string Action = "")
        {
            try
            {
                WFFederate fed = null;
                object m_fed = Data;
                bool blReturn = false;
                MessageEx EventMessage;
                string ClientType = msg.Federation;
                string EventKey;
                fed = (WFFederate)GetFederate(ClientType, msg, m_fed, msg.Address);

                if (fed != null)
                {
                    fed.MakeUpMessage(ClientType, ref msg, Data, Action);
                    fed.BuildWorkQueue(msg);
                }
            }
            catch (Exception ex)
            {
                Tracer.Error(ex.StackTrace, ex);
            }
        }

        public void RECVUI2WCMessage(MessageEx msg)
        {
            try
            {
                WFServiceFederate fed = null;
                fed = (WFServiceFederate)GetFederate("WFServiceFederate", msg, null, "");
                if (fed != null)
                {
                    fed.MakeUpMessage("WFServiceFederate", ref msg, "");
                    fed.BuildWorkQueue(msg);
                }
            }
            catch (Exception ex)
            {
                Tracer.Error(ex.StackTrace, ex);
            }
        }
        public void POSTUI2WFMessage(MessageEx msg)
        {
            try
            {
                WFFederate fed = null;
                fed = (WFFederate)GetFederate("WFFederate", msg, null, msg.Address);
                if (fed != null)
                {
                    fed.MakeUpMessage("WFFederate", ref msg, "");
                    fed.BuildWorkQueue(msg);
                }
            }
            catch (Exception ex)
            {
                Tracer.Error(ex.StackTrace, ex);
            }
        }
        */
        #endregion

        #region =================DocumentFactory=================
        public event PropertyChangedEventHandler DocumentPropertyChanged;
        public void NotifyPropertyChanged(string propertyName)
        {
            if (DocumentPropertyChanged != null)
                DocumentPropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion

        #region =================MESSAGE=================
        /// <summary>
        /// Event delegate
        /// </summary>
        public event EventHandler<MessageEventArgs> OnMessage;

        public void RaiseMessage(MessageInfo info)
        {
            RaiseMessage(new MessageEventArgs(info));
        }

        /// <summary>
        /// Internal function to raise an event
        /// </summary>
        /// <param name="type"></param>
        private void RaiseMessage(MessageEventArgs args)
        {
            RaiseStatus(args.Info.Details, StatusEventType.StopProgress);
            Trace.Assert(args != null);

            if (CheckAccess())
            {
                if (OnMessage != null)
                    OnMessage(this, args);
            }
            else
                Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate
                {
                    if (OnMessage != null)
                        OnMessage(this, args);
                });
        }

        private void RaiseMessage(string message)
        {
            RaiseStatus(message, StatusEventType.StopProgress);
            Trace.TraceInformation(message);

            if (CheckAccess())
            {
                MessageEventArgs args = new MessageEventArgs(message);

                if (OnMessage != null)
                    OnMessage(this, args);
            }
            else
                Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate
                {
                    MessageEventArgs args = new MessageEventArgs(message);

                    if (OnMessage != null)
                        OnMessage(this, args);
                });
        }

        #endregion
        #region POSTRTIMessage
        /*
        /// <summary>
        /// Internal function to raise a project event
        /// </summary>
        /// <param name="type"></param>
        public void POSTRTIMessage(MessageEx msg, object Data, string Action = "")
        {
            try
            {
                object m_fed = Data;
                string ClientType = msg.Federation;
                Federate fed = null;
                fed = (Federate)GetFederate(ClientType, msg, m_fed);
                msg.JobType = "FED2RTI";
                if (fed != null)
                {
                    fed.MakeUpMessage(ClientType, ref msg, Data, msg.JobID);
                    fed.BuildWorkQueue(msg);
                }
            }
            catch (Exception ex)
            {
                Tracer.Error(ex.StackTrace, ex);
            }
        }
        */
        #endregion
        #region =================UIAgent=================
        /*
        /// <summary>
        /// Internal function to raise a project event
        /// </summary>
        /// <param name="type"></param>
        public void POSTUI2UIMessage(MessageEx msg, object Data, string Action = "")
        {
            try
            {
                UIFederate fed = null;
                object m_RTIServiceClient = Data;
                string ClientType = "UIFederate";
                fed = (UIFederate)GetFederate(ClientType, msg, m_RTIServiceClient);
                if (fed != null)
                {
                    fed.MakeUpMessage(ClientType, ref msg, Data, msg.JobID);
                    fed.BuildWorkQueue(msg);
                }
                else
                {
                    Tracer.Warn("EventDispatcher.RaiseUIMessage", ClientType + ":" + msg.Address + " can not find");
                }
            }
            catch (Exception ex)
            {
                Tracer.Error(ex.StackTrace, ex);
            }
        }
        */
        #endregion
    }
}
